﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ShredTheLog.Api;
using System.ComponentModel.Composition;
using System.Reflection;
using ShredTheLog.Plugins;
using System.Windows.Documents;
using System.Windows.Controls;
using System.Diagnostics.Contracts;
using System.Windows.Media;
using System.Windows;

namespace ShredTheLog.Themes
{
    static class Helper
    {
        public static readonly string ThemesAssembly = Assembly.GetExecutingAssembly().FullName;
        
        public static Uri GetThemeUri(string fileName)
        {
            Contract.Requires(!String.IsNullOrWhiteSpace(fileName));
            Contract.Ensures(Contract.Result<Uri>() != null);

            return new Uri(@"pack://application:,,,/" + Helper.ThemesAssembly + ";component/Skins/" + fileName);
        }

        public static ImageSource GetThemeImage(string fileName, string resourceKey)
        {
            Contract.Requires(!String.IsNullOrWhiteSpace(fileName));
            Contract.Requires(!String.IsNullOrWhiteSpace(resourceKey));
            Contract.Ensures(Contract.Result<ImageSource>() != null);

            var resourceDictionary = new ResourceDictionary() { Source = GetThemeUri(fileName) };
            var result = (ImageSource)resourceDictionary[resourceKey];
            Contract.Assume(result != null);
            return result;
        }

        public static ImageSource GetThemeImage(string fileName)
        {
            Contract.Requires(!String.IsNullOrWhiteSpace(fileName));
            Contract.Ensures(Contract.Result<ImageSource>() != null);

            var imageUri = GetThemeUri(fileName);
            var result = (ImageSource)new ImageSourceConverter().ConvertFrom(imageUri);
            Contract.Assume(result != null);
            return result;
        }

        public static ThemeSmiley[] DefaultSmileys
        {
            get
            {
                return new ThemeSmiley[] 
                { 
                    new ThemeSmiley(SmileSmileyDefinition.IDString, text => new Run("☺"){ ToolTip = text }),
                };
            }
        }

        public static ThemeSound[] DefaultSounds
        {
            get
            {
                return new ThemeSound[]
                {
                    new ThemeSound(typeof(IMessageNotificationSource), new Uri(@"Sounds\notify.wav", UriKind.Relative)),
                };
            }
        }
    }

    [Export(typeof(ITheme))]
    [OrderMetadata(Order = 0)]
    [PartCreationPolicy(CreationPolicy.Shared)]
    public sealed class FlashTheme : ITheme
    {
        public const string IDString = "Flash";
        public string ID { get { return IDString; } }
        public string Name { get { return "Flash"; } }

        public ThemeSmiley[] Smileys 
        { 
            get 
            {
                return new ThemeSmiley[] 
                {
                    new ThemeSmiley(SmileSmileyDefinition.IDString, text => GetSmiley("FlashImages/Smileys/Smile.xaml", "SmileSmiley", text)),
                    new ThemeSmiley(GrinSmileyDefinition.IDString, text => GetSmiley("FlashImages/Smileys/Grin.xaml", "GrinSmiley", text)),
                    new ThemeSmiley(ConfusedSmileyDefinition.IDString, text => GetSmiley("FlashImages/Smileys/Confused.xaml", "ConfusedSmiley", text)),
                    new ThemeSmiley(CrySmileyDefinition.IDString, text => GetSmiley("FlashImages/Smileys/Cry.xaml", "CrySmiley", text)),
                    new ThemeSmiley(KissSmileyDefinition.IDString, text => GetSmiley("FlashImages/Smileys/Loving.xaml", "LovingSmiley", text)),
                    new ThemeSmiley(SunglassesSmileyDefinition.IDString, text => GetSmiley("FlashImages/Smileys/Sunglasses.xaml", "SunglassesSmiley", text)),
                };
            }
        }

        public ThemeSound[] Sounds { get { return Helper.DefaultSounds; } }

        private static Inline GetSmiley(string fileName, string resourceKey, string toolTip)
        {
            Contract.Requires(!String.IsNullOrWhiteSpace(fileName));
            Contract.Requires(!String.IsNullOrWhiteSpace(resourceKey));
            Contract.Requires(!String.IsNullOrWhiteSpace(toolTip));
            Contract.Ensures(Contract.Result<Inline>() != null);

            return new InlineUIContainer(new Image() { Source = Helper.GetThemeImage(fileName, resourceKey), ToolTip = toolTip, Width = 16 });
        }
    }

    [Export(typeof(ITheme))]
    [OrderMetadata(Order = 100)]
    [PartCreationPolicy(CreationPolicy.Shared)]
    public sealed class OdigoTheme : ITheme
    {
        public const string IDString = "Odigo";
        public string ID { get { return IDString; } }
        public string Name { get { return "Odigo"; } }

        public ThemeSmiley[] Smileys
        {
            get
            {
                return new ThemeSmiley[] 
                {
                    new ThemeSmiley(SmileSmileyDefinition.IDString, text => GetSmiley("OdigoImages/Smileys/smiling.png", text)),
                    new ThemeSmiley(TongueSmileyDefinition.IDString, text => GetSmiley("OdigoImages/Smileys/tongueout.png", text)),
                    new ThemeSmiley(WinkSmileyDefinition.IDString, text => GetSmiley("OdigoImages/Smileys/winking.png", text)),
                    new ThemeSmiley(GrinSmileyDefinition.IDString, text => GetSmiley("OdigoImages/Smileys/laughing.png", text)),
                    new ThemeSmiley(SadSmileyDefinition.IDString, text => GetSmiley("OdigoImages/Smileys/sad.png", text)),
                    new ThemeSmiley(AngrySmileyDefinition.IDString, text => GetSmiley("OdigoImages/Smileys/angry.png", text)),
                    new ThemeSmiley(KissSmileyDefinition.IDString, text => GetSmiley("OdigoImages/Smileys/loving.png", text)),
                    new ThemeSmiley(HeartSmileyDefinition.IDString, text => GetSmiley("OdigoImages/Smileys/heart.png", text)),
                };
            }
        }

        private static readonly ThemeSound[] _sounds = new ThemeSound[]
        {
            new ThemeSound(typeof(IMessageNotificationSource), new Uri(@"Sounds\Odigo\MsgArrived.wav", UriKind.Relative)),
            new ThemeSound(typeof(ILoginNotificationSource), new Uri(@"Sounds\Odigo\LoadClient.wav", UriKind.Relative)),
        };

        public ThemeSound[] Sounds { get { return _sounds; } }

        private static Inline GetSmiley(string fileName, string toolTip)
        {
            Contract.Requires(!String.IsNullOrWhiteSpace(fileName));
            Contract.Requires(!String.IsNullOrWhiteSpace(toolTip));
            Contract.Ensures(Contract.Result<Inline>() != null);

            return new InlineUIContainer(new Image() { Source = Helper.GetThemeImage(fileName), ToolTip = toolTip, Width = 19 });
        }
    }

    [Export(typeof(ITheme))]
    [OrderMetadata(Order = 200)]
    [PartCreationPolicy(CreationPolicy.Shared)]
    public sealed class SimpleTheme : ITheme
    {
        public const string IDString = "Simple";
        public string ID { get { return IDString; } }
        public string Name { get { return "Simple"; } }

        public ThemeSmiley[] Smileys { get { return Helper.DefaultSmileys; } }

        public ThemeSound[] Sounds { get { return Helper.DefaultSounds; } }
    }

    [Export(typeof(ITheme))]
    [OrderMetadata(Order = 1000)]
    [PartCreationPolicy(CreationPolicy.Shared)]
    public sealed class BureauBlackTheme : ITheme
    {
        public const string IDString = "BureauBlack";
        public string ID { get { return IDString; } }
        public string Name { get { return "Bureau Black"; } }

        public ThemeSmiley[] Smileys { get { return Helper.DefaultSmileys; } }

        public ThemeSound[] Sounds { get { return Helper.DefaultSounds; } }
    }

    [Export(typeof(ITheme))]
    [OrderMetadata(Order = 1000)]
    [PartCreationPolicy(CreationPolicy.Shared)]
    public sealed class BureauBlueTheme : ITheme
    {
        public const string IDString = "BureauBlue";
        public string ID { get { return IDString; } }
        public string Name { get { return "Bureau Blue"; } }

        public ThemeSmiley[] Smileys { get { return Helper.DefaultSmileys; } }

        public ThemeSound[] Sounds { get { return Helper.DefaultSounds; } }
    }

    [Export(typeof(ITheme))]
    [OrderMetadata(Order = 1000)]
    [PartCreationPolicy(CreationPolicy.Shared)]
    public sealed class ExpressionDarkTheme : ITheme
    {
        public const string IDString = "ExpressionDark";
        public string ID { get { return IDString; } }
        public string Name { get { return "Expression Dark"; } }

        public ThemeSmiley[] Smileys { get { return Helper.DefaultSmileys; } }

        public ThemeSound[] Sounds { get { return Helper.DefaultSounds; } }
    }

    [Export(typeof(ITheme))]
    [OrderMetadata(Order = 1000)]
    [PartCreationPolicy(CreationPolicy.Shared)]
    public sealed class ExpressionLightTheme : ITheme
    {
        public const string IDString = "ExpressionLight";
        public string ID { get { return IDString; } }
        public string Name { get { return "Expression Light"; } }

        public ThemeSmiley[] Smileys { get { return Helper.DefaultSmileys; } }

        public ThemeSound[] Sounds { get { return Helper.DefaultSounds; } }
    }

    [Export(typeof(ITheme))]
    [OrderMetadata(Order = 1000)]
    [PartCreationPolicy(CreationPolicy.Shared)]
    public sealed class ShinyBlueTheme : ITheme
    {
        public const string IDString = "ShinyBlue";
        public string ID { get { return IDString; } }
        public string Name { get { return "Shiny Blue"; } }

        public ThemeSmiley[] Smileys { get { return Helper.DefaultSmileys; } }

        public ThemeSound[] Sounds { get { return Helper.DefaultSounds; } }
    }

    [Export(typeof(ITheme))]
    [OrderMetadata(Order = 1000)]
    [PartCreationPolicy(CreationPolicy.Shared)]
    public sealed class ShinyRedTheme : ITheme
    {
        public const string IDString = "ShinyRed";
        public string ID { get { return IDString; } }
        public string Name { get { return "Shiny Red"; } }

        public ThemeSmiley[] Smileys { get { return Helper.DefaultSmileys; } }

        public ThemeSound[] Sounds { get { return Helper.DefaultSounds; } }
    }

    [Export(typeof(ITheme))]
    [OrderMetadata(Order = 1000)]
    [PartCreationPolicy(CreationPolicy.Shared)]
    public sealed class WhistlerBlueTheme : ITheme
    {
        public const string IDString = "WhistlerBlue";
        public string ID { get { return IDString; } }
        public string Name { get { return "Whistler Blue"; } }

        public ThemeSmiley[] Smileys { get { return Helper.DefaultSmileys; } }

        public ThemeSound[] Sounds { get { return Helper.DefaultSounds; } }
    }
}
